
;;************************************************************************
;; boxplot2.lsp 
;; contains code for boxplot  
;; copyright (c) 1993-99 by Forrest W. Young
;;************************************************************************

;;BOXPLOT METHODS

(defmeth boxplot-proto :new-plot 
  (data &key title variable-labels point-labels) 
  (let ((n nil)
        (x nil)
        (loc nil)
        (nvar nil)
        (normed-data nil)
        (jitter 0)
        (color? (and (send (send self :button-overlay) :color-mode) 
                     (> *color-mode* 0)))
        (old-colors nil)
        (old-symbols nil)
        (old-states nil)
        (retain-pt-states (send self :retain-point-states))
        (y-name (send self :y-axis-label)))
    
   (send self :start-buffering)
    (setq data (cond 
                 ((matrixp data) (column-list data))
                 ((or (not (listp data)) (numberp (car data))) (list data))
                 (t data)))
    (send self :data data)
    (setf nobs (length (first data)))
    (setf nvar (length data))
    (when (or (/= nobs (send self :num-obs))
              (/= nvar (send self :num-var)))
          (setf retain-pt-states nil)
          (send self :num-obs nobs)
          (send self :num-var nvar))
    (when (send self :enable-equate)
          (send self :normed-data (send self :normalize data))
          (if (send self :equate)
              (setf data (send self :normed-data))
              (setf data (send self :data))))
    (when (and retain-pt-states (> (send self :num-points) 0)) 
          (setf old-colors 
                (send self :point-color (iseq nobs)))
          (setf old-symbols
                (send self :point-symbol (iseq nobs)))
          (setf old-states
                (send self :point-state (iseq nobs)))
        )
    (send self :clear) 
    (setf n (mapcar #'length data))
    (setf x (* (mean n) (iseq (length n))))
    (send self :x x)
    (when (not variable-labels) 
          (setf variable-labels (repeat "" (length data))))
    (send self :variable-labels variable-labels)
    (let ((range (get-nice-range (min data) (max data) 4)))
      (send self :range 1 (nth 0 range) (nth 1 range))
      (send self :y-axis t t (nth 2 range)))
    (send self :range 0 (- (first x) (/ (first n) 2))
          (+ (last  x) (/ (last  n) 2)))
    (when (not (send self :has-slot 'original-order))
          (dotimes (i nvar)
             (when (send self :jitter)
                   (setf jitter 
                         (* (- (uniform-rand (length (nth i data))) .55) .025
                            (abs (apply (function -) (send self :range 0))))))
             (send self :add-points 
                   (+ jitter (repeat (nth i x) (length (nth i data))))
                   (nth i data))))
    
     (when (send self :has-slot 'original-order) ;this applies to catbox
          
          (setf varx
                (combine (mapcar #'(lambda (i d) 
                                     (+ 
                                      (* (- (uniform-rand (length d)) .55) .025
                                         (abs (apply (function -) (send self :range 0))))
                                      (repeat (nth i x) (length d))))
                                       (iseq nvar) data)))
          (setf vary (combine data))
          (setf order (send self :slot-value 'original-order))
          (setf (select varx order) (select varx (iseq (length varx))))
          (setf (select vary order) (select vary (iseq (length vary))))
          
         (send self :add-points  
               varx vary
          ))

    (send self :point-color (iseq (send self :num-points))
          (if color?
              (if (not old-colors)
                  'blue
                  (repeat old-colors nvar))
              nil))
    (send self :point-symbol (iseq (send self :num-points))
          (if (not old-symbols)
                   'disk ;'dot4 PV returned it to disk
                  (repeat old-symbols nvar)))
    
    ;(when point-labels (send self :showing-labels t))
    (when (not point-labels) 
          (setf point-labels
                (mapcar #'(lambda (i) (format nil "~d" i))
                        (iseq (send self :num-obs)))))
    (when (and (send self :enable-connect-points) 
               (/= (length (combine data)) (length point-labels)))
          (setf point-labels 
                (combine point-labels 
                         (repeat " " (- (length (combine data))
                                        (length point-labels))))))
    (send self :point-label (iseq (length point-labels)) point-labels)
    (send self :variable-label 1 
          (if (send self :equate) 
              (strcat "Normalized " y-name) y-name))
    
    (send self :point-state (iseq (send self :num-points))
          (if (not old-states)
                  'normal
                  (repeat old-states nvar)))
    
    (when (and retain-pt-states (> nvar 1))
          (let* ((ptst (send self :point-state (iseq nobs)))
                 (ptsel 
                  (which (mapcar #'(lambda (i) 
                           (equal 'selected (select ptst i))) 
                                 (iseq nobs)))))
            (when ptsel 
                  (send self :parallel ptsel 'selected nobs nvar))))
    (send self :change-plot)
    (send self :buffer-to-screen))
  )



(defmeth boxplot-proto :adjust-points (pts s &optional mouse-mode)
  (let* ((enabled (send self :enable-connect-points))
         (num-obs (if enabled
                      (send self :num-obs)
                      (length (combine (send self :data)))))
         (num-var (send self :num-var))
         )
;(format t "BP: Adjust Points: ~d~%" (list pts s))
    (when (not mouse-mode) (setf mouse-mode (send self :mouse-mode)))
    (cond 
      ((eq s 'selected) 
       (send self :propagate-selection 
             pts 'selected num-obs num-var mouse-mode)
       )
    ((eq s 'hilited)
     (let* ((point-states (send self :point-state (iseq num-obs)))
            (hilited-pts (which (map-elements #'eq 'hilited point-states)))
            (low-pts (if enabled (when pts (mod pts num-obs)) pts)))
       (when pts
             (send self :propagate-selection 
                   (set-difference hilited-pts low-pts) 'normal 
                   num-obs num-var mouse-mode)
             (send self :propagate-selection 
                   (set-difference low-pts hilited-pts) 'hilited
                    num-obs num-var mouse-mode)
             )
       (when (and hilited-pts (not pts))
             (send self :propagate-selection hilited-pts 'normal
                    num-obs num-var mouse-mode)
             (send self :change-plot))))))
  (when (send self :links)
  (mapcar #'(lambda (plot) (send plot :adjust-screen)) (remove self (send self :links))))
;PV this guarantees that other plots receive the adjust screen message 
;and the regression lines feature will work
)
  
    

(defmeth boxplot-proto :normalize (data)
  (column-list 
   (normalize
    (transpose (matrix (list (length data) (length (first data))) 
                       (combine data))))))

(defmeth boxplot-proto :showing-labels (&optional (logical nil set))
"Args: (&optional logical)
Sets or returns t or nil for whether point and variable labels are showing and causes them to show or not show."
  (when set (call-next-method logical)
        (send self :change-plot))
  (call-next-method))

(defmeth boxplot-proto :do-brush-motion (&rest args)
  (let* ((motion (send self :brush)))
    (send self :dynamic-horizontal-label (first args))
    (apply #'call-next-method args)))

(defmeth boxplot-proto :do-brush-click (x y m1 m2)
  (send self :dynamic-horizontal-label x)
  (call-next-method x y m1 m2))

#|
(defmeth boxplot-proto :dynamic-horizontal-label (x)
  (let* ((data (if (send self :equate) 
                   (send self :normed-data) 
                   (send self :data)))
         (n (mapcar #'length data))
         (ng (length n))
         (raw-xs (+ 10 (send self :x)))
         (xy (send self :horizontal-label-coordinates))
         (xloc (first xy))
         (varlabs (send self :variable-labels))
         (iflag nil) (w) (xmin) (xmax)
         (j (send self :active-label))
         )
    (dotimes (i ng)
             (setf w (/ (nth i n) 2))
             (setf xmin (first (send self :scaled-to-canvas (- (nth i raw-xs) w) 0)))
             (setf xmax (first (send self :scaled-to-canvas (+ (nth i raw-xs) w) 0)))
             (when (< xmin x xmax) (setf iflag i)))
    (cond
      ((and iflag (not (equal iflag j)))
       (when j (send self :horizontal-label varlabs j xloc nil))
       (send self :horizontal-label varlabs iflag xloc t)
       (send self :active-label iflag)
       )
      (iflag
       (send self :horizontal-label varlabs iflag xloc t))
      ((and (not iflag) j)
       (send self :horizontal-label varlabs j xloc nil)
       (send self :active-label nil)
       ))
    ))
|#

(defmeth boxplot-proto :dynamic-horizontal-label (x)
  (let* ((data (if (send self :equate) 
                   (send self :normed-data) 
                   (send self :data)))
         (n (mapcar #'length data))
         (ng (length n))
         (raw-xs (send self :x))
         (xy (send self :horizontal-label-coordinates))
         (xloc (first xy))
         (varlabs (send self :variable-labels))
         (iflag nil) (w) (xmin) (xmax)
         (prv-hotbin (send self :active-label))
         (now-hotbin nil)
         (new-hotbin nil)
         )
    (dotimes (i ng)
             (setf w (/ (nth i n) 3))
             (setf xmin (max (first (send self :scaled-to-canvas (- (nth i raw-xs) w) 0))
                             (first (send self :scaled-to-canvas 
                                          (first (send self :range 0)) 0))))
             (setf xmax (min (first (send self :scaled-to-canvas (+ (nth i raw-xs) w) 0))
                             (first (send self :scaled-to-canvas
                                          (second (send self :range 0)) 0))))
             (when (< xmin x xmax) 
                   (setf now-hotbin i)
                   (when (not (equal prv-hotbin now-hotbin)) ;now in different hotbin
;(print "NEW hot bin")
                         (send self :active-label now-hotbin)
                         (setf new-hotbin t)
                         (when prv-hotbin 
                               (send self :horizontal-label varlabs prv-hotbin xloc nil))
                         (send self :horizontal-label varlabs now-hotbin xloc t)
                         (return))))
    (when (and (and prv-hotbin (not now-hotbin))) ; b4 we were in an interval and now arnt
;(print "NO  hot bin")
          (send self :horizontal-label varlabs prv-hotbin xloc nil)
          (send self :active-label nil))
    ))

(defmeth boxplot-proto :horizontal-label-coordinates ()
  (list
   (mapcar #'(lambda (x) (first (send self :scaled-to-canvas x 0))) (send self :x))
   (+ 5 (second (send self :real-to-canvas 0 (first (send self :range 1)))))
   ))


(defmeth boxplot-proto :horizontal-label (varlabs i x-edge state)
  (let* ((width (+ 6 (send self :text-width (select varlabs i))))
         (height 14)
         (rect-x (- (select x-edge i) (floor (/ width 2))))
         (cr (send self :content-rect))
         (crbottom (+ (second cr) 10 (fourth cr)))
         (rect-y (1+ (+ (second cr) 10 (fourth cr))))
         (j (send self :active-label))
         )
    (if state
        (send self :draw-horizontal-label 
              (select varlabs i) (select x-edge i) crbottom 'red (equal i j))
        (send self :draw-horizontal-label 
              (select varlabs i) (select x-edge i) crbottom 'black))
    ))

#|
(defmeth boxplot-proto :horizontal-label (varlabs i x-edge state)
  (let* ((width (+ 6 (send self :text-width (select varlabs i))))
         (height 14)
         (rect-x (- (select x-edge i) (floor (/ width 2))))
         (cr (send self :content-rect))
         (crbottom (+ (second cr) 10 (fourth cr)))
         (rect-y (1+ (+ (second cr) 10 (fourth cr))))
         (j (send self :active-label))
         )
    (cond
      (state
       ;(send self :draw-color 'white)
       ;(send self :paint-rect (1+ rect-x) (1+ rect-y) (- width 2) (- height 2))
       ;(send self :draw-color 'black)
       ;(send self :frame-rect rect-x rect-y width height)
       (send self :draw-horizontal-label 
             (select varlabs i) (select x-edge i) crbottom 'red (equal i j))
       ;(send self :draw-color 'black)
       )
      (t
       ;(send self :draw-color 'white)
       ;(send self :frame-rect x-edge rect-y width height)
       ;(send self :draw-color 'black)
       (send self :draw-horizontal-label 
             (select varlabs i) (select x-edge i) crbottom 'black )
       ))))


(defmeth boxplot-proto :horizontal-label (varlabs i x-edge state)
  (let* ((width (+ 6 (send self :text-width (select varlabs i))))
         (height 14)
         (rect-x (- (select x-edge i) (floor (/ width 2))))
         (cr (send self :content-rect))
         (crbottom (+ (second cr) 10 (fourth cr)))
         (rect-y (1+ (+ (second cr) 10 (fourth cr))))
         (j (send self :active-label))
         (label (select varlabs i))
         (color (if state 'red 'black))
         )
    (send self :draw-horizontal-label label rect-x rect-y color (equal i j))
    ))
|#
(defmeth boxplot-proto :add-x-axis ()
  (let* ((cr (send self :content-rect))
         (xy (send self :horizontal-label-coordinates))
         (xloc (first xy))
         (yloc (second xy))
         (naxes (length (send self :data))) ;sometimes there are blank axes labels that
         (varlabs (select (send self :variable-labels) (iseq naxes))) ;are ignored
         (xi)
         )
    (dotimes (i naxes)
             (setf xi (select xloc i))
             (send self :draw-line xi yloc xi (+ yloc 5)))
    (send self :draw-horizontal-labels varlabs xloc yloc 'black)
    (send self :draw-text (if (send self :grouped) "Groups" "Variables" )
          (floor (/ (+ (first cr) (third cr)) 2)) (+ yloc 18) 0 1)
    ))

(defmeth boxplot-proto :draw-horizontal-labels 
                      (varlabs xloc yloc color &optional rect)
  (let* ((hotlab (send self :active-label)))
  (dotimes (i (length varlabs))
           (send self :draw-horizontal-label 
                 (select varlabs i) (select xloc i) (+ yloc 5) color (equal i hotlab)))))

(defmeth boxplot-proto :draw-horizontal-label (label x y color &optional hotlab?)
  (let* ((width (+ 6 (send self :text-width label)))
         (rect-x (- x (ceiling (/ width 2))))
         (height 15))
    (send self :draw-color 'white)
    (send self :paint-rect rect-x y width height)
    (send self :draw-color 'black)
    (when hotlab? 
          (send self :frame-rect rect-x y width height)
          (send self :draw-color 'red))
    (send self :draw-text  label x y 1 1)
    (send self :draw-color 'black)
    ))

(defmeth boxplot-proto :add-labels ()
  (let* ((data (send self :data))
         (x (send self :x))
         (n (mapcar #'length data))
         (variable-labels (send self :variable-labels))
         (w 0)
         (cr (send self :content-rect))
         (crbottom (+ (second cr) (fourth cr)))
         (crtop (second cr))
         (shift-left 4)
         (yloc)
         (stwidth)
         (loc nil))
    (when (send self :enable-equate)
          (when (send self :equate) 
                (setf data (send self :normed-data))))
    (send self :add-x-axis)

#|following does vertical labels. codes works fine but is
  replaced by horizontal labels impplement in preceedng statement

    (dotimes (i (length data))
             (if (or (send self :diamonds) (send self :boxes))
                 (setf w (/ (nth i n) 4))
                 (setf w 0))
             (setf ymean (mean (nth i data)))
            ; (if (member 'selected 
            ;             (send self :point-state 
            ;                   (iseq (send self :num-points))))
            ;     (setf yloc (second (send self :real-to-canvas 
            ;                              0 (second (send self :content-rect)))))
            ;     (setf yloc (second (send self :real-to-canvas 0 ymean))))
             (setf yloc (second (send self :real-to-canvas 
                   0 (+ (first (send self :range 1))))))
             (setf stwidth 
                   (floor (/ (send self :text-width (select variable-labels i)) 2)))
             (setf loc (send self :scaled-to-canvas (- (nth i x) w) ymean))
             (if (> (+ stwidth yloc) crbottom)
                 (setf (select loc 1) (- crbottom stwidth)))
                   (if (< (- yloc stwidth) crtop)
                       (setf (select loc 1) (+ crtop stwidth)))
             (send self :draw-text-up (select variable-labels i) 
                   (- (first loc) shift-left) (second loc) 1 0)
             )
|#
    ))
 

(defmeth boxplot-proto :add-diamondplot 
  (y &key (x 1.0) (width 1.0) (draw t))
  (unless (= 2 (send self :num-variables)) (error "only works for 2D plots"))
  (let* ((color (if (and (send (send self :button-overlay) :color-mode) 
                         (> *color-mode* 0)) 'green 'black))
         (half-box (* 0.5 width))
         (half-foot (* 0.1 width))
         (mean (mean y))
         (stdv (standard-deviation y))
         (low (min y))
         (p1 (- mean (if stdv stdv 0)))
         (p3 (+ mean (if stdv stdv 0)))
         (high (max y)))
    (send self :add-lines (list (- x half-box) (+ x half-box))
                          (list mean mean) :color color :width 1)
    (send self :add-lines (list x (- x half-box) x (+ x half-box) x)
                          (list p3 mean p1 mean p3) :color color :width 1)
    ))

(defmeth boxplot-proto :add-boxplot
   (y &key (x 1.0) (width 1) (lwidth 1) (color nil) (draw t)) 
  ;PV modified this to accept color and lwidth arguments
   (unless (= 2 (send self :num-variables)) (error "only works for 2D plots"))
   (let* ((color (if color color
                     (if (and (send (send self :button-overlay) :color-mode)
                              (> *color-mode* 0)) 'red 'black)))
          (half-box (* .5 width))
          (half-foot (* .3 width))
          ;(fiv (fivnum y))
          (tukey (tukey-hinges y));modified to use tukey hinges
          (low (first tukey))
          (q1 (second tukey))
          (med (third tukey))
          (q3 (fourth tukey))
          (high (fifth tukey))
          (num-lines-b4 (send self :num-lines))
          (lwidth lwidth)
          (first-interval-confidence (+ med (* 1.58 (/ (- q3 q1) (sqrt (length y))))))
          (second-interval-confidence (- med (* 1.58 (/ (- q3 q1) (sqrt (length y))))))
          (fourth-box (/ half-box .75))
          )
     ;this adds intervals of confidence around the median
     (send self :add-lines (list (- x fourth-box) (- x fourth-box))
           (list first-interval-confidence second-interval-confidence) 
           :color 'dark-green :width lwidth)
     (send self :add-lines (list (+ x fourth-box) (+ x  fourth-box))
           (list first-interval-confidence second-interval-confidence) 
           :color 'dark-green :width lwidth)
     (send self :add-lines (list (- x fourth-box) (+ x fourth-box))
           (list med med) :color color :width lwidth)
     (send self :add-lines (list (- x fourth-box) (+ x fourth-box))
           (list first-interval-confidence first-interval-confidence) 
           :color 'dark-green :width lwidth)
     (send self :add-lines (list (- x fourth-box) (+ x fourth-box))
           (list second-interval-confidence second-interval-confidence) 
           :color 'dark-green :width lwidth)
     (send self :add-lines (list x x) (list q3 high) :color color :width lwidth)
     (send self :add-lines (list x x) (list q1 low) :color color :width lwidth)
     (send self :add-lines (list (- x half-foot) (+ x half-foot))
                           (list low low) :color color :width lwidth)
     (send self :add-lines (list (- x (* 1.2 fourth-box)) (+ x (* 1.2 fourth-box)))
                           (list med med) :color color :width lwidth)
     ;(send self :add-lines (list (- x half-box) (+ x half-box))
     ;                      (list med med) :color color :width lwidth)
     (send self :add-lines (list (- x half-foot) (+ x half-foot))
                           (list high high) :color color :width lwidth)
     (send self :add-lines (list (- x half-box) (- x half-box)
                                 (+ x half-box) (+ x half-box) (- x half-box))
                           (list q3 q1 q1 q3 q3) :color color :width lwidth)
     (send self :add-lines (list (- x half-box) (- x half-box)
                                 (+ x half-box) (+ x half-box) (- x half-box))
           (list q3 q1 q1 q3 q3) :color color :width lwidth)
     ))

(defun tukey-hinges (var)
  (let* ((var (coerce var 'vector))
         (n (length var))
         (sorted-var (sort-data var))
         (median (median var))
         (length-hinge (if (evenp n) (/ n 2) (/ (1+ n) 2)))
         (low-hinge (if (= length-hinge 1) 
                       	(select sorted-var 0) 
                       	(median (select sorted-var (iseq  0 length-hinge)))))
         (high-hinge (if (= length-hinge 1) 
                         (select sorted-var 0) 
                         (median (select sorted-var (iseq  length-hinge (1- n))))))
         (width-hinges (* 1.5 (- high-hinge low-hinge)))
         (low-whisker (select var (which (>= var (- low-hinge width-hinges)))))
         (low-whisker (if (> (length low-whisker) 0) 
                          (first (sort-data low-whisker)) 
                          low-hinge))
         (high-whisker (select var (which (<= var (+ high-hinge width-hinges)))))
         (high-whisker (if (> (length high-whisker) 0) 
                           (first (last (sort-data high-whisker))) high-hinge)))
    (list low-whisker low-hinge median high-hinge high-whisker)))



(defmeth boxplot-proto :switch-boxes ()
  (send self :boxes (not (send self :boxes)))
  (send self :change-plot))

(defmeth boxplot-proto :switch-diamonds ()
  (send self :diamonds (not (send self :diamonds)))
  (send self :change-plot))

(defmeth boxplot-proto :switch-mean-line ()
  (send self :mean-line (not (send self :mean-line)))
  (send self :change-plot))

(defmeth boxplot-proto :switch-median-line ()
  (send self :median-line (not (send self :median-line)))
  (send self :change-plot))

(defmeth boxplot-proto :switch-connect-points ()
  (send self :connect-points (not (send self :connect-points)))
  (send self :change-plot))

(defmeth boxplot-proto :switch-equate ()
  (send self :equate (not (send self :equate)))
  (let ((point-labels
         (send self :point-label (iseq (send self :num-points)))))
    (send self :new-plot 
          (send self :data)
          :title (send self :title)
          :point-labels point-labels
          :variable-labels (send self :variable-labels))))

(defmeth boxplot-proto :set-selection-color ()
  (call-next-method)
  (send self :adjust-screen))

(defmeth boxplot-proto :change-plot ()
  (let* ((data (if (send self :equate) 
                   (send self :normed-data) 
                   (send self :data)))
         (num-lines-b4 nil)
         
         (color? (and (send (send self :button-overlay) :color-mode)  
                      (> *color-mode* 0)))
         (width (if color? 2 1))
         (n (mapcar #'length data))
         (x (send self :x)))
    (send self :start-buffering)
    (send self :clear-lines)
    (dotimes (i (length data))
             (when (send self :boxes)
                   (send self :add-boxplot (nth i data) 
                         :width (/ (nth i n) 2) :x (nth i x)))
             (when (send self :diamonds)
                   (send self :add-diamondplot (nth i data) 
                         :width (/ (nth i n) 2) :x (nth i x))))
    (when (send self :median-line)
          (setf num-lines-b4 (send self :num-lines))
          (send self :add-lines x (mapcar #'median data) 
                :color (if color? 'red 'black)
                :width width)
          )
    (when (send self :mean-line)
          (setf num-lines-b4 (send self :num-lines))
          (send self :add-lines x (mapcar #'mean data) 
                :color (if color? 'green 'black)
                :width width)
          )
    (send self :redraw)
    (send self :buffer-to-screen)
    ))

(defmeth boxplot-proto :plot-help (&key (flush t))
  (let ((w (plot-help-window (strcat "Help for " (send self :title))
                              :flush flush)))
    (paste-plot-help (format nil 
"The Box, Diamond and Dot plot uses boxes, diamonds and dots to form a schematic of a set of observations. The schematic can give you insight into the shape of the distribution of observations. Some Box, Diamond and Dot plots have several schematics. These side-by-side plots can also help you see if the distributions have the same average value and the same variation in values. ~2%"))
    (paste-plot-help (format nil
"The plot always displays dots. They are located vertically at the value of the observations shown on the vertical scale. (The dots are 'jittered' horizontally by a small random ammount to avoid overlap).~2%"))
    (paste-plot-help (format nil
"The plot can optionally display boxes and diamonds. Boxes summarize information about the quartiles of the variable's distribution. Diamonds summarize information about the moments of the variable's distribution. The BOX and DIAMOND buttons at the bottom of the graph control whether boxes or diamonds (or both) are displayed.~2%"))
(paste-plot-help (format nil
"The box plot is a simple schematic of a variable's distribution. The schematic gives you information about the shape of the distribution of the observations. The schematic is especially useful for determining if the distribution of observations has a symmetric shape. If the portion of the schematic above the middle horizontal line is a reflection of the part below, then the distribution is symmetric. Otherwise, it is not.~2%"))
(paste-plot-help (format nil
"In the box plot, the center horizontal line shows the median, the bottom and top edges of the box are at the first and third quartile, and the bottom and top lines are at the 10th and 90th percentile. Thus, half the data are inside the box, half outside. Also, 10% are above the top line and another 10% are below the bottom line. The width of the box is proportional to the total number of observations.~2%"))
(paste-plot-help (format nil
"The diamond plot is another schematic of the distribution, but it is based on the mean and standard deviation. The center horizontal line is at the mean, and the top and bottom points of the diamond are one standard deviation away from the mean. The width is proportional to the number of observations. The diamond is always symmetric, regardless of whether the distribution is symmetric.~2%"))
(paste-plot-help (format nil
"In side-by-side plots, both the box plot and diamond plot can be used to see if the distributions have the same central tendency and the same variation. If the several medians, as well as the several means, are all about the same, then the central tendency for each distribution is about the same. If the diamonds are all approximately the same size vertically, and if the boxes are also all about the same size vertically, then the distributions have about the same variation.~2%"))
(when (> (length (send self :data)) 1) (paste-plot-help (format nil "The MEDIANS and MEANS buttons control whether boxes are connected at their medians and whether diamonds are connected at their means.")))
(when (send self :enable-connect-points) (paste-plot-help (format nil
" The CONNECT button connects together corresponding observations in  multivariate data. This effectively makes the plot an ANDREWS plot.")))
(show-plot-help)))



(provide "boxplot1")